package cn.jinjimi.app.main.widget;

import android.content.Context;
import android.content.res.Configuration;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.NumberPicker;

import cn.jinjimi.base.util.LogUtil;
import cn.jinjimi.base.util.Lunar;
import cn.jinjimi.app.R;

import java.util.Calendar;

/**
 * 日历控件
 * <p/>
 * 日历显示友好
 * <p/>
 * 增加农历的显示
 * <p/>
 * Created by Jinsen on 2015/8/4.
 */
public class LunarDatePicker extends FrameLayout {

    public enum DATETYPE {
        GREGORIAN(0),//公历
        LUNAR(1),//农历
        ALL(2);// 月日时分

        int value = 0;

        DATETYPE(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    }

    private static final String TAG = "LunarDatePicker";

    private static final int DEFAULT_START_YEAR = 1900;

    private static final int DEFAULT_END_YEAR = 2100;

    private DateTypeChangeListener mDateTypeChange = null;

    //日历显示方式，默认为公历
    private DATETYPE mCurrentDateType = DATETYPE.GREGORIAN;

    private NumberPicker mYearPicker;
    private NumberPicker mMonthPicker;
    private NumberPicker mDayPicker;
    private NumberPicker mHourPicker;
    private NumberPicker mMinutePicker;

    private Calendar mCurrentDate;

    private Context mContext;

    private OnDateChangedListener mOnDateChangedListener;

    private int mYear = 1990;
    private int mMonth = 1;
    private int mDay = 1;
    private int mHour = 0;
    private int mMinute = 0;

    private Calendar mCalendar = Calendar.getInstance();
    private String mDateStr = null;

    //农历的闰月
    private int mLeapMonth = 0;

    private int mMonthMaxDay = 31;

    final static String mMonthNumber[] = {"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"};
    final static String mChineseNumber[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};

    public static String getChinaDayString(int day) {
        String chineseTen[] = {"初", "十", "廿", "三"};
        int n = day % 10 == 0 ? 9 : day % 10 - 1;
        if (day > 30)
            return "";
        if (day == 10)
            return "初十";
        else
            return chineseTen[day / 10] + mChineseNumber[n];
    }


    /* 日历类型切换监听 */
    public interface DateTypeChangeListener {
        void onDateTypeChange(DATETYPE type);
    }

    /* The callback used to indicate the user changes\d the date. */
    public interface OnDateChangedListener {

        /**
         * @param view
         * @param date    所有的都返回公历的日期
         * @param dateStr 日期字符串 公历的 2015年1月日 农历 二零一五年一月初一
         * @param type    日期类型
         */
        void onDateChanged(LunarDatePicker view, Calendar date, String dateStr, DATETYPE type);
    }

    public LunarDatePicker(Context context) {
        this(context, null);
    }

    public LunarDatePicker(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LunarDatePicker(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mContext = context;

        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.date_picker_layout, this, true);

        NumberPicker.OnValueChangeListener onChangeListener = new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                if (picker == mDayPicker) {
                    mDay = newVal;
                } else if (picker == mMonthPicker) {
                    mMonth = newVal;
                    mMonthMaxDay = getMonthMaxDay(mYear, mMonth);
                    if (mDay > mMonthMaxDay) {
                        mDay = mDay - mMonthMaxDay;
                    }
                } else if (picker == mYearPicker) {
                    mYear = newVal;
                    mLeapMonth = Lunar.leapMonth(mYear);
                    mMonthMaxDay = getMonthMaxDay(mYear, mMonth);
                    if (mDay > mMonthMaxDay) {
                        mDay = mDay - mMonthMaxDay;
                    }
                } else if (picker == mHourPicker) {
                    mHour = newVal;
                } else if (picker == mMinutePicker) {
                    mMinute = newVal;
                }
                updateSpinners();
                notifyDateChanged();
            }
        };

        mCurrentDate = Calendar.getInstance();
        mCurrentDate.setTimeInMillis(System.currentTimeMillis());

        mYearPicker = (NumberPicker) findViewById(R.id.year);
        mYearPicker.setOnValueChangedListener(onChangeListener);
        mYearPicker.setOnLongPressUpdateInterval(300);
        mYearPicker.setMinValue(1900);
        mYearPicker.setMaxValue(2045);

        mMonthPicker = (NumberPicker) findViewById(R.id.month);
        mMonthPicker.setOnValueChangedListener(onChangeListener);
        mMonthPicker.setOnLongPressUpdateInterval(300);

        mDayPicker = (NumberPicker) findViewById(R.id.day);
        mDayPicker.setOnValueChangedListener(onChangeListener);
        mDayPicker.setOnLongPressUpdateInterval(300);

        mHourPicker = (NumberPicker) findViewById(R.id.hour);
        mHourPicker.setMinValue(0);
        mHourPicker.setMaxValue(23);
        mHourPicker.setOnValueChangedListener(onChangeListener);
        mHourPicker.setOnLongPressUpdateInterval(300);

        mMinutePicker = (NumberPicker) findViewById(R.id.minute);
        mMinutePicker.setMinValue(0);
        mMinutePicker.setMaxValue(59);
        mMinutePicker.setOnValueChangedListener(onChangeListener);
        mMinutePicker.setOnLongPressUpdateInterval(300);

    }

    /**
     * 设置当前显示的日历类型
     * DATE_TYPE
     *
     * @param type
     */
    public void setDateType(DATETYPE type) {
        if (type == mCurrentDateType)
            return;

        if (type == DATETYPE.GREGORIAN || type == DATETYPE.ALL) {
            if (mMonth > 11)//预防农历年有闰月，在农历12月转公历
                mMonth = 11;
        }

        if (type == DATETYPE.ALL) {
            mYearPicker.setVisibility(GONE);
            mHourPicker.setVisibility(VISIBLE);
            mMinutePicker.setVisibility(VISIBLE);
        }

        this.mCurrentDateType = type;
        if (mCurrentDateType == DATETYPE.GREGORIAN || type == DATETYPE.GREGORIAN) {//农历转公历
            mLeapMonth = 0;
        } else {//公历转农历
            mLeapMonth = Lunar.leapMonth(mYear);
        }

        mMonthMaxDay = getMonthMaxDay(mYear, mMonth);
        if (mDay > mMonthMaxDay) mDay = mMonthMaxDay;
        if (mDayPicker.getMaxValue() > mMonthMaxDay) {
            updateSpinners();
            setDatePickerDisplayName();
        } else {
            setDatePickerDisplayName();
            updateSpinners();
        }

//        if (mCurrentDateType == DATETYPE.LUNAR && mYearPicker.isShown()) {
//            mYearPicker.setVisibility(GONE);
//            mYearPicker.setVisibility(VISIBLE);
//        }

        notifyDateChanged();
    }

    /**
     * 获取当前的日历类型
     *
     * @return
     */
    public DATETYPE getDateType() {
        return mCurrentDateType;
    }

    /**
     * 是否显示年份
     *
     * @param visible
     */
    public void setYearVisible(int visible) {
        mYearPicker.setVisibility(visible);

        if (mYearPicker.isShown()) {
            setDate(mYear, mMonth, mDay, mHour, mMinute);
        } else {
            mLeapMonth = 0;
            setDate(2015, mMonth, mDay, mHour, mMinute);
        }

        mMonthMaxDay = getMonthMaxDay(mYear, mMonth);
        if (mDay > mMonthMaxDay) mDay = mDay - mMonthMaxDay;
        if (mDayPicker.getMaxValue() > mMonthMaxDay) {
            updateSpinners();
            setDatePickerDisplayName();
        } else {
            setDatePickerDisplayName();
            updateSpinners();
        }
        notifyDateChanged();
    }

    /**
     * 是否已显示年份
     *
     * @return
     */
    public boolean showYear() {
        return mYearPicker.getVisibility() == View.VISIBLE;
    }

    /**
     * 是否显示日期
     *
     * @param visible
     */
    public void setDayVisible(int visible) {
        mDayPicker.setVisibility(visible);
    }

    /**
     * 是否已显示日期
     *
     * @return
     */
    public boolean showDay() {
        return mDayPicker.isShown();
    }

    /**
     * @return The selected year.
     */
    public int getYear() {
        return mYear;
    }

    /**
     * @return The selected month.
     */
    public int getMonth() {
        return mMonth;
    }

    /**
     * @return The selected day of month.
     */
    public int getDayOfMonth() {
        return mDay;
    }

    /**
     * @return The selected hour
     */
    public int getHour() {
        return mHour;
    }

    /**
     * @return The selected minute
     */
    public int getMinute() {
        return mMinute;
    }

    /**
     * 获取设置的日期
     *
     * @return
     */
    public Calendar getDate() {
        return mCalendar;
    }

    /**
     * 获取日期字符串
     *
     * @return
     */
    public String getDateStr() {
        return mDateStr;
    }

    /**
     * 初始化
     *
     * @param year
     * @param monthOfYear
     * @param dayOfMonth
     * @param type                  设置日历类型
     * @param onDateChangedListener
     */
    public void init(int year, int monthOfYear, int dayOfMonth, int hour, int minute, DATETYPE type,
                     OnDateChangedListener onDateChangedListener) {
        setDateType(type);
        this.mCurrentDateType = type;
        setDate(year, monthOfYear, dayOfMonth, hour, minute);
        updateSpinners();
        setDatePickerDisplayName();
        mOnDateChangedListener = onDateChangedListener;
        initDateInfo();
    }

    public void updateDate(int year, int monthOfYear, int dayOfMonth, DATETYPE type) {
        updateDate(year, monthOfYear, dayOfMonth, 0, 0, type);
    }

    public void updateDate(int year, int monthOfYear, int dayOfMonth, int hour, int minute, DATETYPE type) {
        setDate(year, monthOfYear, dayOfMonth, hour, minute);
        if (type != mCurrentDateType)
            setDateType(type);
        else {
            updateSpinners();
        }
        notifyDateChanged();
    }


    /**
     * Notifies the listener, if such, for a change in the selected date.
     */
    private void notifyDateChanged() {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
        if (mOnDateChangedListener != null) {
            initDateInfo();
            mOnDateChangedListener.onDateChanged(this, mCalendar, mDateStr, mCurrentDateType);
//            LogUtil.e(TAG, "current date  :: " + mCalendar.getTimeInMillis() + " 日期 : " + mDateStr
//                    + " yy:mm:dd ;: " + mCalendar.get(Calendar.YEAR) + "-" + (mCalendar.get(Calendar.MONTH)+1) + "-" + mCalendar.get(Calendar.DAY_OF_MONTH));
        }
    }

    private void initDateInfo() {
        if (mCurrentDateType == DATETYPE.LUNAR) {
            mCalendar = Lunar.lunar2Gregorian(getYear(), getMonth(), getDayOfMonth(), mLeapMonth);
            if (showYear()) {
                mDateStr = getLunarYearStr(getYear()) + getLunarMonthStr(getMonth(), mLeapMonth) + getChinaDayString(getDayOfMonth());
            } else {
                mDateStr = getLunarMonthStr(getMonth(), mLeapMonth) + getChinaDayString(getDayOfMonth());
            }
        } else if (mCurrentDateType == DATETYPE.GREGORIAN) {
            mCalendar.set(getYear(), getMonth(), getDayOfMonth());
            if (showYear()) {
                mDateStr = getYear() + "年" + (getMonth() + 1) + "月" + getDayOfMonth() + "日";
            } else {
                mDateStr = (getMonth() + 1) + "月" + getDayOfMonth() + "日";
            }
        } else if (mCurrentDateType == DATETYPE.ALL) {
            mCalendar.set(getYear(), getMonth(), getDayOfMonth(), getHour(), getMinute());
            mDateStr = (getMonth() + 1) + "月" + getDayOfMonth() + "日  " + getHour() + ":" + getMinute();
        }
        LogUtil.e(TAG, mDateStr + " " + showYear());
    }

    private void setDate(int year, int month, int dayOfMonth, int hour, int minute) {
        mYear = year;
        mMonth = month;
        mLeapMonth = Lunar.leapMonth(mYear);
        mMonthMaxDay = getMonthMaxDay(mYear, mMonth);
        mDay = dayOfMonth > mMonthMaxDay ? mMonthMaxDay : dayOfMonth;
        mHour = hour;
        mMinute = minute;
    }

    //设置日历显示样式
    private void setDatePickerDisplayName() {
        if (mCurrentDateType == DATETYPE.GREGORIAN || mCurrentDateType == DATETYPE.ALL) {
            String[] displayedDay = new String[31];
            for (int i = 0; i < 31; i++) {
                displayedDay[i] = (i + 1) + "日";
            }
            mDayPicker.setDisplayedValues(displayedDay);

            //预防在农历转公历时，农历有闰月，出现索引
            if (mMonthPicker.getMaxValue() > 11)
                mMonthPicker.setMaxValue(11);
            String[] displayedMonth = new String[12];
            for (int i = 0; i < 12; i++) {
                displayedMonth[i] = (i + 1) + "月";
            }
            mMonthPicker.setDisplayedValues(displayedMonth);

            int maxYear = mYearPicker.getMaxValue() - mYearPicker.getMinValue() + 1;
            String[] displayYear = new String[maxYear];
            for (int i = 0; i < maxYear; i++) {
                displayYear[i] = (1900 + i) + "年";
            }
            mYearPicker.setDisplayedValues(displayYear);

            String[] displayHour = new String[24];
            for (int i = 0; i < 24; i++) {
                displayHour[i] = i < 10 ? ("0" + i + "时") : i + "时";
            }
            mHourPicker.setDisplayedValues(displayHour);

            String[] displayMinute = new String[60];
            for (int i = 0; i < 60; i++) {
                displayMinute[i] = i < 10 ? ("0" + i + "分") : i + "分";
            }
            mMinutePicker.setDisplayedValues(displayMinute);

        } else {
            String[] displayedDay = new String[30];
            for (int i = 0; i < 30; i++) {
                displayedDay[i] = getChinaDayString(i + 1);
            }
            mDayPicker.setDisplayedValues(displayedDay);

            int maxYear = mYearPicker.getMaxValue() - mYearPicker.getMinValue() + 1;
            String[] displayYear = new String[maxYear];
            for (int i = 0; i < maxYear; i++) {
                int y = 1900 + i;
                displayYear[i] = getLunarYearStr(y);
            }
            mYearPicker.setDisplayedValues(displayYear);
        }
    }


    public final String getLunarYearStr(int year) {
        return mNumber2Str[year / 1000]
                + mNumber2Str[(year % 1000) / 100]
                + mNumber2Str[(year % 100) / 10]
                + mNumber2Str[year % 10] + "年";
    }

    final String[] mNumber2Str = new String[]{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};

    private String getLunarMonthStr(int month, int leapMonth) {
        String monthStr = null;
        if (leapMonth > 0) {
            if (month < mLeapMonth)
                monthStr = mMonthNumber[month] + "月";
            else
                monthStr = mMonthNumber[month - 1] + "月";

            if (mLeapMonth == month)
                monthStr = "闰" + mMonthNumber[month - 1] + "月";

        } else {
            if (month > 11) --month;
            monthStr = mMonthNumber[month] + "月";
        }
        return monthStr;
    }

    //设置农历的月份
    private void setLunarMonthDisplay() {
        int m = mLeapMonth > 0 ? 13 : 12;
        String[] displayedMonth = new String[m];
        for (int i = 0; i < m; i++) {
            displayedMonth[i] = getLunarMonthStr(i, mLeapMonth);
        }

        if (m < mMonthPicker.getMaxValue() + 1)
            mMonthPicker.setMaxValue(m - 1);
        mMonthPicker.setDisplayedValues(displayedMonth);
        mMonthPicker.setMaxValue(m - 1);
    }

    private void updateSpinners() {
        // set the spinner ranges respecting the min and max dates
        mDayPicker.setWrapSelectorWheel(true);
        mMonthPicker.setMinValue(0);
        mMonthPicker.setWrapSelectorWheel(true);

        mDayPicker.setMinValue(1);
        mDayPicker.setMaxValue(mMonthMaxDay);

        if (mCurrentDateType == DATETYPE.GREGORIAN || mCurrentDateType == DATETYPE.ALL) {
            mMonthPicker.setMaxValue(11);
        } else {
            //TODO 闰月的处理
            setLunarMonthDisplay();
        }

        mYearPicker.setWrapSelectorWheel(false);

        mYearPicker.setValue(mYear);
        mMonthPicker.setValue(mMonth);
        mDayPicker.setValue(mDay);
        mHourPicker.setValue(mHour);
        mMinutePicker.setValue(mMinute
        );
    }

    //获取公历月份天数
    //根据年月获取月份的天数
    private int getGregorianMonthMaxDay(int year, int month) {
        int dayMax = 31;
        month++;
        switch (month) {
            case 4:
            case 6:
            case 9:
            case 11:
                dayMax = 30;
                break;
            case 2://TODO 闰年 平年
                if (year % 4 == 0)
                    dayMax = 29;
                else
                    dayMax = 28;
                break;
            default:
                dayMax = 31;
                break;
        }
        return dayMax;
    }

    //获取农历月份天数
    //根据农历的年月获取月份天数 农历的月份是1开始
    private int getLunarMonthMaxDay(int year, int month) {
        if (mLeapMonth > 0) {
            if (month < mLeapMonth) return Lunar.monthDays(year, month + 1);
            else if (month == mLeapMonth) return Lunar.leapDays(year);
            else return Lunar.monthDays(year, month);
        }
        return Lunar.monthDays(year, month + 1);
    }

    //获取月份天数
    private int getMonthMaxDay(int year, int month) {
        if (mCurrentDateType == DATETYPE.GREGORIAN || mCurrentDateType == DATETYPE.ALL) {
            return getGregorianMonthMaxDay(year, month);
        } else {
            return getLunarMonthMaxDay(year, month);
        }
    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        onPopulateAccessibilityEvent(event);
        return true;
    }

    @Override
    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
        super.onPopulateAccessibilityEvent(event);

        final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
        String selectedDateUtterance = DateUtils.formatDateTime(mContext,
                mCurrentDate.getTimeInMillis(), flags);
        event.getText().add(selectedDateUtterance);
    }

    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);
        event.setClassName(LunarDatePicker.class.getName());
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);
//        info.setClassName(LunarDatePicker.class.getName());
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }


    /**
     * 公历转农历
     */



}
